package config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    DataSource dataSource;

    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {

        /**
         * 用数据库来验证用户名和密码
         * 如果不使用usersByUsernameQuery和authoritiesByUsernameQuery，那么默认需要有users和authorities两张表，两张表的结构也是确定的
         * 参考：http://docs.spring.io/spring-security/site/docs/4.2.3.RELEASE/reference/htmlsingle/#jc-authentication-jdbc
         * 如果使用usersByUsernameQuery和authoritiesByUsernameQuery,则可以从自定义的表中读取用户信息，只要返回的信息和Spring Security匹配即可
         */
        auth.jdbcAuthentication().dataSource(dataSource)
                /*.usersByUsernameQuery(
                        "select name,pass, enabled from users where name=?")
                .authoritiesByUsernameQuery(
                        "select name, role from user_roles where name=?")*/;
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        //auth.inMemoryAuthentication().withUser("admin").password("123456").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
                .and().formLogin()
                .loginPage("/login")
                /**
                 * http://localhost:8080/j_spring_security_check,使用spring-security框架，自定义login页面时，发现上面的请求404
                 * 原因：
                 *     spring-security的版本问题，spring-security4.x版本，若需要自定义login页面时，需要自定login-processing-url=“/j_spring_security_check”
                 *     spring-security3.x版本，不需要手动加
                 */
                .loginProcessingUrl("/j_spring_security_check")
                .failureUrl("/login?error")
                .usernameParameter("username")
                .passwordParameter("password")
                .and()
                /**
                 * 这里的logoutUrl指定的路径，当用户访问这个路径时，会被Spring Security捕获到，然后进行登出操作，登出成功，重定向到logoutSuccessUrl
                 */
                .logout().invalidateHttpSession(true).logoutUrl("/j_spring_security_logout").logoutSuccessUrl("/login?logout")
                .and()
                .exceptionHandling().accessDeniedPage("/403")
                .and()
                .csrf();
    }
}
